<script lang="ts" setup>
import { uploadCheck, uploadChunk, uploadHWYun } from '@/api/upload';
import { message } from 'ant-design-vue';

const { index, title, chapterIndex, hwyunId ,episid} = defineProps<{
  index: number
  title: string
  chapterIndex: number
  notAllowOperation?: boolean
  hwyunId?: string
  episid:number
}>()

// 修改父组件数据
const emit = defineEmits<{
  (e: 'del-episode', chapterIndex: number, index: number): void
  (e: 'edit-episode', chapterIndex: number, index: number, title: string): void
}>()


// 是否编辑控制变量
let isEditState = ref(false)

let titleContent = ref(title)

// 集标题编辑或保存
function editEpisode() {
  if (isEditState.value) {
    emit('edit-episode', chapterIndex, index, titleContent.value)
  }
  isEditState.value = !isEditState.value
}

// 处理上传视频的逻辑
const uploadVideo = ref<HTMLElement>()

// 初始化视频文件信息
let fileReactive = ref({
  file: undefined as File | undefined,
  hash: '',
  type: '',
  uploadedBytes: 0,
  offset: 0,
  size: 0,
  isLoading: false,
  title: ''
})


// 上传具体视频文件
async function handleUpload() {
  fileReactive.value.isLoading = true
  if (!fileReactive.value.file) {
    alert('请选择文件')
    return
  }
  // 校验视频是否上传、没上传或者没完成则继续
  const { data, code } = await uploadCheck({
    hash: fileReactive.value.hash,
    type: fileReactive.value.type
  })
  if (code !== 0) {
    fileReactive.value.isLoading = false
    message.error('上传失败，请重试')
    resetFileReactive()
    return
  }
  // 上传的视频字节数
  fileReactive.value.uploadedBytes = data.uploadedBytes

  // 定义键值对的表单、值必须为字符串
  const formData = new FormData()
  formData.append('hash', fileReactive.value.hash)
  formData.append('title', fileReactive.value.title)
  formData.append('size', String(fileReactive.value.size))
  formData.append('type', fileReactive.value.type.split('/').pop()!)
  console.log(fileReactive.value.uploadedBytes < fileReactive.value.size);

  // 当已经上传的文件字节数小于该文件的总字节数，则继续上传
  while (fileReactive.value.uploadedBytes < fileReactive.value.size) {
    // 切分的起点
    const startByte = fileReactive.value.uploadedBytes
    // 切分结束点，每次上传视频的固定为10兆
    const endByte = Math.min(startByte + 1024 * 1024 * 10, fileReactive.value.size)
    // 切分文件上传
    const chunk = fileReactive.value.file.slice(startByte, endByte)
    // 开始的位置
    formData.append('offset', String(startByte))
    // 把上一次的删除，插入新chunk
    formData.delete('chunk')
    formData.append('chunk', chunk)
    // 上传视频文件
    const { data: uploadData, code: uploadCode } = await uploadChunk(formData)
    if (uploadCode !== 0) {
      fileReactive.value.isLoading = false
      message.error('上传失败，请重试')
      resetFileReactive()
      return
    }
    // 更新上传的字节数
    fileReactive.value.uploadedBytes = uploadData.uploadedBytes;
  }
  // 当该视频文件全部上传完成，上传华为云
  await new Promise((resolve) => {
    // 文件IO操作需要时间，延时1秒操作
    setTimeout(async () => {
     
      const { code, msg } = await uploadHWYun({ title: fileReactive.value.title, episodeId: episid, type: fileReactive.value.type })
      if (code === 0) {
        message.success(msg || '上传成功')
      }
      resolve('')
    }, 2000);
  })
}

// 重置文件信息
function resetFileReactive() {
  fileReactive.value = {
    file: undefined,
    hash: '',
    type: '',
    uploadedBytes: 0,
    offset: 0,
    size: 0,
    isLoading: false,
    title: ''
  }
}

// 视频上传点击
async function handleFileChange(e: Event) {
  const file = (e.target as HTMLInputElement).files![0]
  if (file) {
    fileReactive.value.file = file
    fileReactive.value.hash = await getFileHash(file)
    fileReactive.value.type = file.type
    fileReactive.value.offset = 0
    fileReactive.value.uploadedBytes = 0
    fileReactive.value.size = file.size
    fileReactive.value.title = file.name

    await handleUpload().finally(() => resetFileReactive())
  }
}
// 拿到视频文件的hash
function getFileHash(file: File): Promise<string> {
  return new Promise((resolve) => {
    // 创建FileReader对象，用于读取文件内容
    const reader = new FileReader()
    // 将文件内容作为ArrayBuffer类型的对象传递给onload事件处理函数
    reader.onload = async function () {
      const arrayBuffer = reader.result as ArrayBuffer;
      // 计算哈希值
      crypto.subtle.digest("SHA-256", arrayBuffer)
        .then(hash => {
          const hashArray = Array.from(new Uint8Array(hash));
          // 将其转换为字符串格式
          const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
          resolve(hashHex)
        })
    }
    // 读取文件内容
    reader.readAsArrayBuffer(file)
  })
}

function handleVideoUpload() {
  uploadVideo.value?.click()
}
</script>

<template>
  <div border="~" p="x-2 y-1" flex items-center justify-between text-base w-full>
    <div flex="~ v-center" gap-4>
      <div flex="~ v-center" gap="0.8">
        <span flex-shrink-0>第{{ index + 1 }}集</span>
        <span v-show="!isEditState">{{ titleContent }}</span>
        <a-input text="base!" v-model:value="titleContent" v-show="isEditState" />
      </div>
    </div>
    <div flex="~ v-center" gap-4 v-if="!notAllowOperation">
      <a-button type="dashed" size="small" @click="editEpisode">{{ isEditState ? '保存' : '编辑'
      }}</a-button>
      <a-button v-show="!isEditState" type="primary" size="small" danger
        @click="$emit('del-episode', chapterIndex, index)">删除</a-button>
    </div>

    <div v-else>
      <input type="file" hidden ref="uploadVideo" @change="handleFileChange" />
      <a-button type="primary" :loading="fileReactive.isLoading" @click="handleVideoUpload()" style="background-color:#1677ff">{{ hwyunId ? '修改视频' : '上传视频'
      }}</a-button>
    </div>
  </div>
</template>
